package com.ruoyi.web.controller.tool.wxpay;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.ContentType;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethodEnum;
import com.ijpay.core.kit.AesUtil;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.*;
import com.ijpay.wxpay.model.v3.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.web.core.utils.WxPayV3Bean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.*;

@RequestMapping({"/v3"})
@Controller
/* loaded from: WxPayV3Controller.class */ public class WxPayV3Controller {
    private static final int    OK  = 200;
    private final        Logger log = LoggerFactory.getLogger(getClass());
    @Resource
    WxPayV3Bean wxPayV3Bean;
    String serialNo;
    String platSerialNo;

    @RequestMapping({""})
    @ResponseBody
    public String index() {
        this.log.info(this.wxPayV3Bean.toString());
        try {
            this.log.info("absolutePath:{}", PayKit.getAbsolutePath("classpath:/dev/apiclient_key.pem"));
            this.log.info("classPath content:{}", PayKit.getCertFileContent("classpath:/dev/apiclient_key.pem"));
            InputStream inputStream = PayKit.getCertFileInputStream("classpath:/dev/wxpay_v3.properties");
            if (null != inputStream) {
                ByteArrayOutputStream result = new ByteArrayOutputStream();
                byte[]                buffer = new byte[1024];
                while (true) {
                    int length = inputStream.read(buffer);
                    if (length == -1) {
                        break;
                    }
                    result.write(buffer, 0, length);
                }
                this.log.info("file content:{}", result);
            }
            return "欢迎使用 IJPay 中的微信支付 Api-v3 -By Javen  <br/><br>  交流群：723992875、864988890";
        } catch (Exception e) {
            this.log.error("文件不存在", e);
            return "欢迎使用 IJPay 中的微信支付 Api-v3 -By Javen  <br/><br>  交流群：723992875、864988890";
        }
    }

    @RequestMapping({"/getSerialNumber"})
    @ResponseBody
    public String serialNumber() {
        return getSerialNumber();
    }

    @RequestMapping({"/getPlatSerialNumber"})
    @ResponseBody
    public String platSerialNumber() {
        return getPlatSerialNumber();
    }

    private String getSerialNumber() {
        X509Certificate certificate;
        if (StrUtil.isEmpty(this.serialNo) && null != (certificate = PayKit.getCertificate(this.wxPayV3Bean.getCertPath()))) {
            this.serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
            this.log.info("证书是否可用 {} 证书有效期为 {}", Boolean.valueOf(PayKit.checkCertificateIsValid(certificate, this.wxPayV3Bean.getMchId(), -2)), DateUtil.format(certificate.getNotAfter(), "yyyy-MM-dd HH:mm:ss"));
        }
        System.out.println("serialNo:" + this.serialNo);
        return this.serialNo;
    }

    private String getPlatSerialNumber() {
        if (StrUtil.isEmpty(this.platSerialNo)) {
            this.platSerialNo = PayKit.getCertificate(FileUtil.getInputStream(this.wxPayV3Bean.getPlatformCertPath())).getSerialNumber().toString(16).toUpperCase();
        }
        System.out.println("platSerialNo:" + this.platSerialNo);
        return this.platSerialNo;
    }

    private String savePlatformCert(String associatedData, String nonce, String cipherText, String certPath) {
        try {
            String publicKey = new AesUtil(this.wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8)).decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText);
            new FileWriter(certPath).write(publicKey);
            return PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes())).getSerialNumber().toString(16).toUpperCase();
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/platformCert"})
    @ResponseBody
    public String platformCert() {
        try {
            return savePlatformCert("certificate", "80d28946a64a", "DwAqW4+4TeUaOEylfKEXhw+XqGh/YTRhUmLw/tBfQ5nM9DZ9d+9aGEghycwV1jwo52vXb/t6ueBvBRHRIW5JgDRcXmTHw9IMTrIK6HxTt2qiaGTWJU9whsF+GGeQdA7gBCHZm3AJUwrzerAGW1mclXBTvXqaCl6haE7AOHJ2g4RtQThi3nxOI63/yc3WaiAlSR22GuCpy6wJBfljBq5Bx2xXDZXlF2TNbDIeodiEnJEG2m9eBWKuvKPyUPyClRXG1fdOkKnCZZ6u+ipb4IJx28n3MmhEtuc2heqqlFUbeONaRpXv6KOZmH/IdEL6nqNDP2D7cXutNVCi0TtSfC7ojnO/+PKRu3MGO2Z9q3zyZXmkWHCSms/C3ACatPUKHIK+92MxjSQDc1E/8faghTc9bDgn8cqWpVKcL3GHK+RfuYKiMcdSkUDJyMJOwEXMYNUdseQMJ3gL4pfxuQu6QrVvJ17q3ZjzkexkPNU4PNSlIBJg+KX61cyBTBumaHy/EbHiP9V2GeM729a0h5UYYJVedSo1guIGjMZ4tA3WgwQrlpp3VAMKEBLRJMcnHd4pH5YQ/4hiUlHGEHttWtnxKFwnJ6jHr3OmFLV1FiUUOZEDAqR0U1KhtGjOffnmB9tymWF8FwRNiH2Tee/cCDBaHhNtfPI5129SrlSR7bZc+h7uzz9z+1OOkNrWHzAoWEe3XVGKAywpn5HGbcL+9nsEVZRJLvV7aOxAZBkxhg8H5Fjt1ioTJL+qXgRzse1BX1iiwfCR0fzEWT9ldDTDW0Y1b3tb419MhdmTQB5FsMXYOzqp5h+Tz1FwEGsa6TJsmdjJQSNz+7qPSg5D6C2gc9/6PkysSu/6XfsWXD7cQkuZ+TJ/Xb6Q1Uu7ZB90SauA8uPQUIchW5zQ6UfK5dwMkOuEcE/141/Aw2rlDqjtsE17u1dQ6TCax/ZQTDQ2MDUaBPEaDIMPcgL7fCeijoRgovkBY92m86leZvQ+HVbxlFx5CoPhz4a81kt9XJuEYOztSIKlm7QNfW0BvSUhLmxDNCjcxqwyydtKbLzA+EBb2gG4ORiH8IOTbV0+G4S6BqetU7RrO+/nKt21nXVqXUmdkhkBakLN8FUcHygyWnVxbA7OI2RGnJJUnxqHd3kTbzD5Wxco4JIQsTOV6KtO5c960oVYUARZIP1SdQhqwELm27AktEN7kzg/ew/blnTys/eauGyw78XCROb9F1wbZBToUZ7L+8/m/2tyyyqNid+sC9fYqJoIOGfFOe6COWzTI/XPytCHwgHeUxmgk7NYfU0ukR223RPUOym6kLzSMMBKCivnNg68tbLRJHEOpQTXFBaFFHt2qpceJpJgw5sKFqx3eQnIFuyvA1i8s2zKLhULZio9hpsDJQREOcNeHVjEZazdCGnbe3Vjg7uqOoVHdE/YbNzJNQEsB3/erYJB+eGzyFwFmdAHenG5RE6FhCutjszwRiSvW9F7wvRK36gm7NnVJZkvlbGwh0UHr0pbcrOmxT81xtNSvMzT0VZNLTUX2ur3AGLwi2ej8BIC0H41nw4ToxTnwtFR1Xy55+pUiwpB7JzraA08dCXdFdtZ72Tw/dNBy5h1P7EtQYiKzXp6rndfOEWgNOsan7e1XRpCnX7xoAkdPvy40OuQ5gNbDKry5gVDEZhmEk/WRuGGaX06CG9m7NfErUsnQYrDJVjXWKYuARd9R7W0aa5nUXqz/Pjul/LAatJgWhZgFBGXhNr9iAoade/0FPpBj0QWa8SWqKYKiOqXqhfhppUq35FIa0a1Vvxcn3E38XYpVZVTDEXcEcD0RLCu/ezdOa6vRcB7hjgXFIRZQAka0aXnQxwOZwE2Rt3yWXqc+Q1ah2oOrg8Lg3ETc644X9QP4FxOtDwz/A==", this.wxPayV3Bean.getPlatformCertPath());
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/get"})
    @ResponseBody
    public String v3Get() {
        try {
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), OtherApiEnum.GET_CERTIFICATES.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), "");
            response.getHeader("Wechatpay-Timestamp");
            response.getHeader("Wechatpay-Nonce");
            String serialNumber = response.getHeader("Wechatpay-Serial");
            response.getHeader("Wechatpay-Signature");
            String body   = response.getBody();
            int    status = response.getStatus();
            this.log.info("serialNumber: {}", serialNumber);
            this.log.info("status: {}", Integer.valueOf(status));
            this.log.info("body: {}", body);
            if (status == 200) {
                JSONObject encryptObject      = JSONUtil.parseObj(body).getJSONArray(AjaxResult.DATA_TAG).getJSONObject(0);
                JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
                String     associatedData     = encryptCertificate.getStr("associated_data");
                String     cipherText         = encryptCertificate.getStr("ciphertext");
                String     nonce              = encryptCertificate.getStr("nonce");
                String     serialNo           = encryptObject.getStr("serial_no");
                this.log.info("平台证书序列号: {} serialNo: {}", savePlatformCert(associatedData, nonce, cipherText, this.wxPayV3Bean.getPlatformCertPath()), serialNo);
            }
            System.out.println("verifySignature:" + WxPayKit.verifySignature(response, this.wxPayV3Bean.getPlatformCertPath()));
            return body;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping({"/nativePay"})
    @ResponseBody
    public String nativePay() {
        try {
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(this.wxPayV3Bean.getAppId()).setMchid(this.wxPayV3Bean.getMchId()).setDescription("IJPay 让支付触手可及").setOut_trade_no(PayKit.generateStr()).setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 180000)).setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX").setNotify_url(this.wxPayV3Bean.getDomain().concat("/v3/payNotify")).setAmount(new Amount().setTotal(1));
            this.log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.NATIVE_PAY.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel));
            this.log.info("统一下单响应 {}", response);
            this.log.info("verifySignature: {}", Boolean.valueOf(WxPayKit.verifySignature(response, this.wxPayV3Bean.getPlatformCertPath())));
            return response.getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/jsApiPay"})
    @ResponseBody
    public String jsApiPay(@RequestParam(value = "openId", required = false, defaultValue = "o-_-itxuXeGW3O1cxJ7FXNmq8Wf8") String openId) {
        try {
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel().setAppid(this.wxPayV3Bean.getAppId()).setMchid(this.wxPayV3Bean.getMchId()).setDescription("IJPay 让支付触手可及").setOut_trade_no(PayKit.generateStr()).setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 180000)).setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX").setNotify_url(this.wxPayV3Bean.getDomain().concat("/v3/payNotify")).setAmount(new Amount().setTotal(1)).setPayer(new Payer().setOpenid(openId));
            this.log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.JS_API_PAY.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel));
            this.log.info("统一下单响应 {}", response);
            boolean verifySignature = WxPayKit.verifySignature(response, this.wxPayV3Bean.getPlatformCertPath());
            this.log.info("verifySignature: {}", Boolean.valueOf(verifySignature));
            if (response.getStatus() != 200 || !verifySignature) {
                return JSONUtil.toJsonStr(response);
            }
            Map<String, String> map = WxPayKit.jsApiCreateSign(this.wxPayV3Bean.getAppId(), JSONUtil.parseObj(response.getBody()).getStr("prepay_id"), this.wxPayV3Bean.getKeyPath());
            this.log.info("唤起支付参数:{}", map);
            return JSONUtil.toJsonStr(map);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/put"})
    @ResponseBody
    public String put() {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("url", "https://gitee.com/javen205/IJPay");
            IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.PUT, WxDomainEnum.CHINA.toString(), ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(params));
            this.log.info("verifySignature: {}", Boolean.valueOf(WxPayKit.verifySignature(response, this.wxPayV3Bean.getPlatformCertPath())));
            this.log.info("响应 {}", response);
            return response.getBody();
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/getParams"})
    @ResponseBody
    public String payScoreServiceOrder() {
        try {
            Map<String, String> params = new HashMap<>();
            params.put("service_id", "500001");
            params.put("appid", "wxd678efh567hg6787");
            params.put("out_order_no", "1234323JKHDFE1243252");
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), PayScoreApiEnum.PAY_SCORE_SERVICE_ORDER.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), params);
            System.out.println(result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/delete"})
    @ResponseBody
    public String v3Delete() {
        try {
            HashMap<String, String> hashMap = new HashMap<>(12);
            hashMap.put("url", "https://qq.com");
            System.out.println(WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(hashMap)));
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.DELETE, WxDomainEnum.CHINA.toString(), ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), "");
            System.out.println("verifySignature:" + WxPayKit.verifySignature(result, this.wxPayV3Bean.getPlatformCertPath()));
            System.out.println(result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/upload"})
    @ResponseBody
    public String v3Upload() {
        try {
            File                    file   = FileUtil.newFile("/Users/Javen/Documents/pic/cat.png");
            Object                  sha256 = SecureUtil.sha256(file);
            HashMap<Object, Object> map    = new HashMap<>();
            map.put("filename", file.getName());
            map.put("sha256", sha256);
            String body = JSONUtil.toJsonStr(map);
            System.out.println(body);
            IJPayHttpResponse result = WxPayApi.v3(WxDomainEnum.CHINA.toString(), OtherApiEnum.MERCHANT_UPLOAD_MEDIA.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), body, file);
            System.out.println("verifySignature:" + WxPayKit.verifySignature(result, this.wxPayV3Bean.getPlatformCertPath()));
            System.out.println(result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/post"})
    @ResponseBody
    public String payGiftActivity() {
        try {
            String urlSuffix = String.format(PayGiftActivityApiEnum.PAY_GIFT_ACTIVITY_TERMINATE.toString(), "10028001");
            System.out.println(urlSuffix);
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), urlSuffix, this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), "");
            System.out.println(result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/sensitive"})
    @ResponseBody
    public String sensitive() {
        try {
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), Apply4SubApiEnum.APPLY_4_SUB.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), getPlatSerialNumber(), this.wxPayV3Bean.getKeyPath(), "处理请求参数");
            System.out.println(result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/cipher"})
    @ResponseBody
    public String cipher() {
        try {
            System.out.println(PayKit.rsaEncryptOAEP("IJPay", PayKit.getCertificate(FileUtil.getInputStream(this.wxPayV3Bean.getPlatformCertPath()))));
            System.out.println(PayKit.rsaDecryptOAEP("", PayKit.getPrivateKey(this.wxPayV3Bean.getKeyPath())));
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/tradeBill"})
    @ResponseBody
    public String tradeBill(@RequestParam(value = "billDate", required = false) String billDate) {
        try {
            if (StrUtil.isEmpty(billDate)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(5, -1);
                billDate = DateUtil.format(calendar.getTime(), "YYYY-MM-dd");
            }
            Map<String, String> params = new HashMap<>(12);
            params.put("bill_date", billDate);
            params.put("bill_type", "ALL");
            params.put("tar_type", "GZIP");
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), BasePayApiEnum.TRADE_BILL.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), params);
            this.log.info("verifySignature: {}", Boolean.valueOf(WxPayKit.verifySignature(result, this.wxPayV3Bean.getPlatformCertPath())));
            this.log.info("result:{}", result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/fundFlowBill"})
    @ResponseBody
    public String fundFlowBill(@RequestParam(value = "billDate", required = false) String billDate) {
        try {
            if (StrUtil.isEmpty(billDate)) {
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(5, -1);
                billDate = DateUtil.format(calendar.getTime(), "YYYY-MM-dd");
            }
            Map<String, String> params = new HashMap<>(12);
            params.put("bill_date", billDate);
            params.put("account_type", "BASIC");
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), BasePayApiEnum.FUND_FLOW_BILL.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), params);
            this.log.info("verifySignature: {}", Boolean.valueOf(WxPayKit.verifySignature(result, this.wxPayV3Bean.getPlatformCertPath())));
            this.log.info("result:{}", result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/billDownload"})
    @ResponseBody
    public String billDownload(@RequestParam("token") String token, @RequestParam(value = "tarType", required = false) String tarType) {
        try {
            Map<String, String> params = new HashMap<>(12);
            params.put(Constants.TOKEN, token);
            if (StrUtil.isNotEmpty(tarType)) {
                params.put("tartype", tarType);
            }
            IJPayHttpResponse result = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), BasePayApiEnum.BILL_DOWNLOAD.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), params);
            this.log.info("result:{}", result);
            return JSONUtil.toJsonStr(result);
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping({"/refund"})
    @ResponseBody
    public String refund(@RequestParam(required = false) String transactionId, @RequestParam(required = false) String outTradeNo) {
        try {
            String outRefundNo = PayKit.generateStr();
            this.log.info("商户退款单号: {}", outRefundNo);
            List<RefundGoodsDetail> list = new ArrayList<>();
            list.add(new RefundGoodsDetail().setMerchant_goods_id("123").setGoods_name("IJPay 测试").setUnit_price(1).setRefund_amount(1).setRefund_quantity(1));
            RefundModel refundModel = new RefundModel().setOut_refund_no(outRefundNo).setReason("IJPay 测试退款").setNotify_url(this.wxPayV3Bean.getDomain().concat("/v3/refundNotify")).setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY")).setGoods_detail(list);
            if (StrUtil.isNotEmpty(transactionId)) {
                refundModel.setTransaction_id(transactionId);
            }
            if (StrUtil.isNotEmpty(outTradeNo)) {
                refundModel.setOut_trade_no(outTradeNo);
            }
            this.log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel));
            IJPayHttpResponse response        = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.REFUND.toString(), this.wxPayV3Bean.getMchId(), getSerialNumber(), null, this.wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(refundModel));
            boolean           verifySignature = WxPayKit.verifySignature(response, this.wxPayV3Bean.getPlatformCertPath());
            this.log.info("verifySignature: {}", Boolean.valueOf(verifySignature));
            this.log.info("退款响应 {}", response);
            if (verifySignature) {
                return response.getBody();
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return e.getMessage();
        }
    }

    @RequestMapping(value = {"/payNotify"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void payNotify(HttpServletRequest request, HttpServletResponse response) {
        Map<String, String> map = new HashMap<>(12);
        try {
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce     = request.getHeader("Wechatpay-Nonce");
            String serialNo  = request.getHeader("Wechatpay-Serial");
            String signature = request.getHeader("Wechatpay-Signature");
            this.log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature);
            String result = HttpKit.readData(request);
            this.log.info("支付通知密文 {}", result);
            String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, this.wxPayV3Bean.getApiKey3(), this.wxPayV3Bean.getPlatformCertPath());
            this.log.info("支付通知明文 {}", plainText);
            if (StrUtil.isNotEmpty(plainText)) {
                response.setStatus(200);
                map.put(AjaxResult.CODE_TAG, "SUCCESS");
                map.put("message", "SUCCESS");
            }
            else {
                response.setStatus(500);
                map.put(AjaxResult.CODE_TAG, "ERROR");
                map.put("message", "签名错误");
            }
            response.setHeader("Content-type", ContentType.JSON.toString());
            response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
